/**
 * 
 */
package edu.gatech.oad.mule.model;

import java.io.Serializable;
import java.util.Enumeration;
import java.util.Vector;

import edu.gatech.oad.mule.model.interfaces.GameStateMachineListener;

/**
 * Keeps track of a current game state and maintains a list of listeners who are
 * notified when the game state changes.
 * 
 * @author Dale Avery
 * @version %I%, %G%
 */
public abstract class GameStateMachine implements Serializable {

	private static final long serialVersionUID = 3583366824474718872L;
	/**
	 * A set of all the possible game states. These should map to phases in a
	 * game of Mule.
	 * 
	 * @author Dale Avery
	 * 
	 */
	public static enum GameState {
		INTRO, PLAYER_RANKING, LAND_GRANT, DEVELOPMENT, PRODUCTION, ERROR
	};

	protected GameState state;

	transient private Vector<GameStateMachineListener> _listeners;

	/**
	 * Constructs a new GameStateMachine object.
	 * 
	 * @param startState
	 *            The desired starting state of the state machine.
	 */
	public GameStateMachine(GameState startState) {
		state = startState;
	}

	/**
	 * Constructs a new GameStateMachine object. Starting state is assumed to be
	 * INTRO.
	 */
	public GameStateMachine() {
		this(GameState.INTRO);
	}

	/**
	 * Add's a given listener to the list of listeners who will be notified when
	 * a game state change occurs.
	 * 
	 * @param listener
	 *            The listener to be added to the list.
	 */
	public final void addActionListener(GameStateMachineListener listener) {
		if (_listeners == null)
			_listeners = new Vector<GameStateMachineListener>();

		_listeners.addElement(listener);
	}

	/**
	 * Sends notification to all listeners that a state change has occurred.
	 */
	protected final void changeState(GameState newState) {
		state = newState;
		if (_listeners != null && !_listeners.isEmpty()) {
			Enumeration<GameStateMachineListener> listeners = _listeners
					.elements();
			while (listeners.hasMoreElements()) {
				GameStateMachineListener listener = (GameStateMachineListener) listeners
						.nextElement();
				listener.stateChange(state);
			}
		}
	}
}
